//
//  AppDelegate.m
//  test-CoreAnimation
//
//  Created by 杨岑 on 12/31/14.
//  Copyright (c) 2014 杨岑. All rights reserved.
//

#import "AppDelegate.h"
#import <QuartzCore/QuartzCore.h>
#import "AnimationController.h"


@interface AppDelegate ()

@property (weak) IBOutlet NSWindow *window;
@property (weak) IBOutlet NSImageView *image1;
@property (weak) IBOutlet NSImageView *image2;
@property (weak) IBOutlet NSImageView *image3;
@property (weak) IBOutlet NSBox *box;
@property (weak) IBOutlet NSView *view;
@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Insert code here to initialize your application
}

- (void)applicationWillTerminate:(NSNotification *)aNotification {
    // Insert code here to tear down your application
}

- (CALayer*)findTestLayer
{
    for (CALayer* x in _box.layer.sublayers) {
        if ([x.name isEqualToString:@"test"]) {
            NSLog(@"Found layer: %@", x.name);
            return x;
        }
    }
    return nil;
}

- (IBAction)test_click:(id)sender {
    CALayer* layer = [self findTestLayer];
    
    if (!layer)
    {
        NSImage* image = [NSImage imageNamed:NSImageNameColorPanel];
        layer = [CALayer layer];
        layer.name = @"test";
        layer.borderWidth = 1;
        layer.contents = image;
        layer.bounds = NSMakeRect(0, 0, image.size.width, image.size.height);
        layer.position = NSMakePoint(image.size.width / 2, _box.bounds.size.height / 2);
        [_box.layer addSublayer:layer];
    }
    
    CGPoint startPos = layer.position;
    CGPoint stopPos = startPos;
    stopPos.x += 100;
    
    layer.position = stopPos;
    CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"position.x"];
    anim.fromValue = @(startPos.x);
    anim.toValue = @(stopPos.x);
    anim.duration = 1.5;
    anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];

    [layer addAnimation:anim forKey:@"test"];
}

- (CAAnimation*)createFadingAnimation:(CALayer*)layer
{
    CGFloat start = layer.opacity;
    CGFloat stop = 1 - layer.opacity;
    layer.opacity = stop;
    
    CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"opacity"];
    anim.fromValue = @(start);
    anim.toValue = @(stop);
    anim.duration = .2;
    anim.timingFunction = [CAMediaTimingFunction functionWithName:stop > 0 ? kCAMediaTimingFunctionEaseIn : kCAMediaTimingFunctionEaseOut];
    return anim;
}

- (IBAction)test2_click:(id)sender {
    CALayer* layer = self.image1.layer;
    
    CAAnimation* anim = [self createFadingAnimation:layer];
    AnimationController* ac = [[AnimationController alloc] init];
    ac.onFinish = ^void(CAAnimation* anim, AnimationController* ac, BOOL f) {
        CALayer* runningLayer = layer.presentationLayer;
        NSLog(@"Result opacity: %.3f %.3f", layer.opacity, runningLayer.opacity);
        
        if ([self.image1.image.name isEqualToString:NSImageNameFolderBurnable])
        {
            self.image1.image = [NSImage imageNamed:NSImageNameFolderSmart];
        }
        else
        {
            self.image1.image = [NSImage imageNamed:NSImageNameFolderBurnable];
        }
        CAAnimation* anim2 = [self createFadingAnimation:layer];
        [layer addAnimation:anim2 forKey:@"opacity"];
    };
    anim.duration = .15;
    anim.delegate = ac;

    [layer addAnimation:anim forKey:@"opacity"];
}

- (IBAction)test3_click:(id)sender {
    static NSMutableArray* subviews;
    
    if (!subviews)
    {
        subviews = [NSMutableArray arrayWithCapacity:10];
        for (int i = 0; i < 10; i++)
        {
            NSImageView* iv = [[NSImageView alloc] init];
            iv.image = [NSImage imageNamed:NSImageNameMobileMe];
            iv.frame = NSMakeRect(iv.image.size.width * i + 5, 0, iv.image.size.width, iv.image.size.height);
            
            [_box addSubview:iv];
            NSLog(@"subviews.count: %ld", _box.subviews.count);
            iv.wantsLayer = YES;
            
            [subviews addObject:iv];
        }
    }
    
    for (int i = 0; i < subviews.count; i++)
    {
        NSImageView* iv = subviews[i];

        CGFloat start = iv.layer.position.x;
        CGFloat stop = 400;
        
        CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"position.x"];
        anim.fromValue = @(start);
        anim.toValue = @(stop);
        anim.duration = 3;
        anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
        //iv.layer.frame = NSMakeRect(stop, iv.layer.position.y, iv.layer.frame.size.width, iv.layer.frame.size.height);
        [iv.layer addAnimation:anim forKey:@"a"];
    }
}

- (CAAnimation*)createViewToViewAnimation:(NSImageView*)fromView to:(NSImageView*)toView
{
    AnimationController* ac = [[AnimationController alloc] init];
    ac.state = @[fromView, toView, fromView.image, toView.image];
    ac.onFinish = ^void(CAAnimation* anim, AnimationController* ac, BOOL f) {
        toView.image = ac.state[2];
    };
    
    CGFloat start = fromView.frame.origin.x;
    CGFloat stop = toView.frame.origin.x;
    
    CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"position.x"];
    anim.fromValue = @(start);
    anim.toValue = @(stop);
    anim.duration = .3;
    anim.delegate = ac;
    anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    [fromView.layer addAnimation:anim forKey:@"a"];
    return anim;
}

- (IBAction)test4_click:(id)sender {
    //[[self findTestLayer] removeAllAnimations];
    [self createViewToViewAnimation:self.image1 to:self.image2];
    [self createViewToViewAnimation:self.image2 to:self.image3];
    [self createViewToViewAnimation:self.image3 to:self.image1];
}

- (CAAnimation*)createImageViewFadeInOutAnimation:(NSImageView*)imageView fromImage:(NSImage*)fromImage toImage:(NSImage*)toImage
{
    AnimationController* ac = [[AnimationController alloc] init];
    ac.state = @[imageView, toImage];
    ac.onStart = ^void(CAAnimation* anim, AnimationController* ac) {
        if (fromImage && (imageView.image != fromImage)) imageView.image = fromImage;
    };
    ac.onFinish = ^void(CAAnimation* anim, AnimationController* ac, BOOL f) {
        AnimationController* ac2 = [[AnimationController alloc] init];
        ac2.state = @[imageView, toImage];
        ac2.onStart = ^void(CAAnimation* anim, AnimationController* ac) {
            imageView.image = toImage;
        };
        ac2.onFinish = ^void(CAAnimation* anim, AnimationController* ac, BOOL f) {
            
        };

        CABasicAnimation* anim2 = [CABasicAnimation animationWithKeyPath:@"opacity"];
        anim2.fromValue = @(0);
        anim2.toValue = @(1);
        anim2.duration = .3;
        anim2.delegate = ac2;
        anim2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
        imageView.layer.opacity = 1;
        [imageView.layer addAnimation:anim2 forKey:@"fadeIn"];
    };
    
    CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"opacity"];
    anim.fromValue = @(1);
    anim.toValue = @(0);
    anim.duration = .3;
    anim.delegate = ac;
    anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    imageView.layer.opacity = 0;
    [imageView.layer addAnimation:anim forKey:@"fadeOut"];
    return anim;
}

- (IBAction)test5_click:(id)sender {
    [self createImageViewFadeInOutAnimation:self.image1 fromImage:self.image1.image toImage:self.image3.image];
    [self createImageViewFadeInOutAnimation:self.image2 fromImage:self.image2.image toImage:self.image1.image];
    [self createImageViewFadeInOutAnimation:self.image3 fromImage:self.image3.image toImage:self.image2.image];
}

- (IBAction)test6_click:(id)sender {
    /*
    NSView* view = self.window.contentView;
    NSBitmapImageRep* imageRep = [view bitmapImageRepForCachingDisplayInRect:view.visibleRect];
    NSData* data = [imageRep representationUsingType:NSPNGFileType properties:nil];
    [data writeToFile:@"/Users/edward/Pictures/test.png" atomically:NO];*/
    static int i;
    NSImageView* imageViews[] = {self.image1, self.image2};
    
    NSImageView* imageView = imageViews[i % 2];
    [imageView.layer removeAllAnimations];
    
    AnimationController* ac = [[AnimationController alloc] init];
    ac.state = @[imageView];
    ac.onStart = ^void(CAAnimation* anim, AnimationController* ac) {
        
    };
    ac.onFinish = ^void(CAAnimation* anim, AnimationController* ac, BOOL f) {
    };
    
    CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:@"opacity"];
    anim.fromValue = @(1);
    anim.toValue = @(0);
    anim.duration = 1.15;
    anim.delegate = ac;
    anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    imageView.layer.opacity = 0;
    [imageView.layer addAnimation:anim forKey:@"fadeOut"];
    i++;
    
    imageView = imageViews[i % 2];
    [imageView.layer removeAllAnimations];
    
    anim = [CABasicAnimation animationWithKeyPath:@"opacity"];
    anim.fromValue = @(0);
    anim.toValue = @(1);
    anim.duration = 2.2;
    //anim.delegate = ac;
    anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    imageView.layer.opacity = 1;
    [imageView.layer addAnimation:anim forKey:@"fadeOut"];
    i++;
    i++;
}

@end
